
module fifo
#(
   parameter                DWID = 32,
   parameter                AWID = 10
)
(
   input                    wclk,
   input                    we,
   input      [DWID-1:0]    wdata,
   output     [2**AWID-1:0] wlevel,
   input                    rclk,
   input                    re,
   output     [DWID-1:0]    rdata,
   output     [2**AWID-1:0] rlevel
);

   reg  [DWID-1:0] ram_int [0:2**AWID-1];
   reg  [AWID-1:0] waddr = 0;
   wire [AWID-1:0] waddr_sync;
   reg  [AWID-1:0] raddr = 0;
   wire [AWID-1:0] raddr_sync;
   reg  [DWID-1:0] rdata_last;

   always @(posedge wclk)
   begin
      if(we)
         waddr <= waddr + 1;
   end
   
   always @(posedge wclk)
   begin
      if(we)
         ram_int[waddr] <= wdata;
   end
   
   sync_clock
   #(
      .DWID              ( AWID )
   )
   u0_sync_clock
   (
      .idata             ( raddr ),
      .oclk              ( wclk ),
      .odata             ( raddr_sync )
   );
   
   assign wlevel = waddr - raddr_sync;
   
   always @(posedge rclk)
   begin
      if(re)
         raddr <= raddr + 1;
   end
   
   always @(posedge rclk)
   begin
      if(re)
         rdata_last <= rdata;
   end

   assign rdata = (re)? ram_int[raddr] : rdata_last;
   
   sync_clock
   #(
      .DWID              ( AWID )
   )
   u1_sync_clock
   (
      .idata             ( waddr ),
      .oclk              ( rclk ),
      .odata             ( waddr_sync )
   );
   
   assign rlevel = waddr_sync - raddr;

endmodule